package concurrent;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Masche enhaelt eine Liste von Knoten einer Masche und stellt verschiedene Methoden zur Verfuegung.
 * Um in einer Masche etwas zu aendern muss man erst das Lock der Masche nehmen. 
 * @author Lukas Subel, Patrick Bender
 */
public class Masche {
	
	/**
	 * The list with all the nodes contained by the masche.
	 */
	private List<Node> masche;

	
	/**
	 * The lock of the masche
	 */
	private ReentrantLock lock = new ReentrantLock();
	
	/**
	 * Versucht das Lock zu Locken
	 */
	public boolean tryLock() {
		return lock.tryLock();
	}
	
	/**
	 * Gibt den Status des Locks der Masche zurueck
	 * @return Lock-Status des Locks
	 */
	public boolean isLocked() {
		return lock.isLocked();
	}
	
	/**
	 * lockt das Lock der Masche
	 */
	public void lock() {
		lock.lock();
	}
	
	/**
	 * unlockt das Lock der Masche
	 */
	public void unlock() {
		lock.unlock();
	}
	
	/**
	 * Give the list of all nodes contained by the masche.
	 * @return The list.
	 */
	public List<Node> getNodes() {
		return masche;
	}
	
	/**
	 * Default constructor;
	 * initialize a new empty list.
	 */
	public Masche() {
		this.masche = new LinkedList<Node>();
	}
	

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		String erg = lock.isLocked() + ":{";
		for(Node act : masche)
		{
			erg += act.getId() + ", ";
		}
		if (masche.size() == 0) erg += "  ";
		return erg.substring(0, erg.length()-2) + "}";
	}

	/**
	 * Add a node to the masche. Set the masche of the node.
	 * @param node The node to add. Checks if the argument is null.
	 */
	public void add(Node node) {
		if (node == null) throw new IllegalArgumentException("Node can't be null");
		//add the node to the masche
		this.masche.add(node);
		//and set the masche of the node
		node.setMasche(this);
	}
	
	/**
	 * Gib die Groese der Masche zurueck
	 * @return Groese der Masche
	 */
	public int getSize() {
		return this.masche.size();
	}

	/**
	 * Check if the masche contains all nodes of an given collection of nodes.
	 * @param c the given collection.
	 * @return True if the masche contains all nodes.
	 */
	public boolean containsAll(Collection<?> c) {
		return this.masche.containsAll(c);
	}
	
	/**
	 * Remove a node from the masche.
	 * @param act The node to remove.
	 * @return True, when the node was successfully removed.
	 */
	public boolean remove(Node act) {
		return this.masche.remove(act);
	}
	
}
